//
//  RDNetModel.swift
//  test-ios
//
//  Created by wyz5204 on 2023/5/31.
//

import Foundation
import Moya
import SwiftyJSON
import RxSwift
import SwiftyRSA

class RDNetModel {
    
    static var shared = RDNetModel()
    
    private var myProvider = MoyaProvider<RDService>(plugins: [ NetworkLoggerPlugin.init(configuration: .init(logOptions: [.formatRequestAscURL,.successResponseBody, .errorResponseBody]))])
    
    private func judgeStatus<T: Codable>(by statusCode: Int, _ data: Data, _ object: T.Type) -> NetworkResult<T> {
        
        guard let decodedData = try? JSONDecoder().decode(JHResponse<T>.self, from: data)
        else {
            return .pathErr
        }
        
        switch statusCode {
        case 200..<205:
            guard decodedData.result != nil else {
                print("⛔️ \(self) 解码错误⛔️")
                return .decodedErr
            }
            return .success(decodedData.result!)
        case 400..<500:
            return .requestErr(decodedData.reason ?? "请求错误")
        case 500:
            return .serverErr
        default:
            return .networkFail
        }
    }
    
    public func disposeNetwork<T: Codable>(_ result: Result<Response, MoyaError>,
                                           dataModel: T.Type,
                                           completion: @escaping (NetworkResult<T>) -> Void) {
        switch result{
        case .success(let response):
            let statusCode = response.statusCode
            let data = response.data
            completion(self.judgeStatus(by: statusCode, data, dataModel.self))
        case .failure(let err):
            print(err)
        }
    }
}

extension RDNetModel {
    
    // 老式的网络请求和数据格式化
    func login(phone : String ,code : String, completion: @escaping (NetworkResult<JSON>) -> Void){
        myProvider.request(.login(username: phone, password: code , pem: "")) { (result) in
            self.disposeNetwork(result,dataModel: JSON.self ,completion: completion)
        }
    }
    
    // 获取当前用户组织列表
    func getOrgList()-> Single<RDResponse<[OrgBean]>>{
        return myProvider.rx.request(.getOrgList).mapAny(RDResponse<[OrgBean]>.self)
    }
    
    // 登陆
    func login(phone : String ,code : String) -> Single<JSON>{
        return getRSAKey().flatMap { [weak self] keyJson -> Single<JSON> in
            guard let this = self else {
                return .error(EmptyError("weak self is null"))
            }
            guard let stringKey = keyJson["data"].rawString() else {
                return .error(EmptyError("key is null"))
            }
            
            do {
                let publicKey = try PublicKey(pemEncoded: stringKey)
                let clear = try ClearMessage(string: code, using: .utf8)
                let encrypted = try clear.encrypted(with: publicKey, padding: .PKCS1)
                return this.myProvider.rx.request(.login(username: phone, password: encrypted.base64String , pem: stringKey)).mapJson()
            } catch {
                return .error(EmptyError("key is null"))
            }
        }
    }
    
    // 登陆
    func loginObj(phone : String ,code : String) -> Single<RDResponse<LoginBean>>{
        return getRSAKey().flatMap { [weak self] keyJson -> Single<RDResponse<LoginBean>> in
            guard let this = self else {
                return .error(EmptyError("weak self is null"))
            }
            guard let stringKey = keyJson["data"].rawString() else {
                return .error(EmptyError("key is null"))
            }
            
            do {
                let publicKey = try PublicKey(pemEncoded: stringKey)
                let clear = try ClearMessage(string: code, using: .utf8)
                let encrypted = try clear.encrypted(with: publicKey, padding: .PKCS1)
                
                return this.myProvider.rx.request(.login(username: phone, password: encrypted.base64String , pem: stringKey)).mapAny(RDResponse<LoginBean>.self)
            } catch {
                return .error(EmptyError("key is null"))
            }
        }
    }
    // 获取RSA key
    func getRSAKey()-> Single<JSON>{
        return myProvider.rx.request(.getRSAKey).mapJson()
    }
    
    // 进行根据组织获取项目列表
    func getProjectList(_ orgId : Int) -> Single<RDResponse<[ProjectBean]>>{
        myProvider.rx.request(.getProjectList(orgId:orgId)).mapAny(RDResponse<[ProjectBean]>.self)
    }
    
    // 获取会话列表 这里需要分页
    func getSessionList()-> Single<RDResponse<SessionBean>>{
        return myProvider.rx.request(.getSessionList).mapAny(RDResponse<SessionBean>.self)
    }
    
    // 获取会话中的消息列表，
    func pullChatMessage(sessionId : String , sessionType : Int , seqId : String , size : Int = 19 , upDown : Bool = true) -> Single<RDResponse<[ChatMessageBean]>>{
        
        let params = ChatMessageParams(sessionId: sessionId, sessionType: sessionType, seqId: seqId, size: size, upDown: upDown)
        return myProvider.rx.request(.pullChatMessage(request: params)).mapAny(RDResponse<[ChatMessageBean]>.self)
    }
}
